// 条件编译：仅在 APP-PLUS 平台（5+ App）下执行

import { resolve } from 'patch-package/dist/path'

// #ifdef APP-PLUS
const AudioFileManager = {
  // 获取主Activity上下文
  main: plus.android.runtimeMainActivity(),

  // 导入Android原生类
  Environment: plus.android.importClass('android.os.Environment'),
  StatFs: plus.android.importClass('android.os.StatFs'),
  BufferedWriter: plus.android.importClass('java.io.BufferedWriter'),
  BufferedReader: plus.android.importClass('java.io.BufferedReader'),
  File: plus.android.importClass('java.io.File'),
  FileOutputStream: plus.android.importClass('java.io.FileOutputStream'),
  FileInputStream: plus.android.importClass('java.io.FileInputStream'),
  OutputStreamWriter: plus.android.importClass('java.io.OutputStreamWriter'),
  InputStreamReader: plus.android.importClass('java.io.InputStreamReader'),
  BufferedOutputStream: plus.android.importClass(
    'java.io.BufferedOutputStream'
  ),
  BufferedInputStream: plus.android.importClass('java.io.BufferedInputStream'),
  fileLib: uni.requireNativePlugin?.('file-tool'),

  // 音频存储路径
  AudioPath: '',
  AppPath: '',

  /**
   * 初始化音频存储路径
   * 优先使用外部存储，不可用时回退到内部存储
   */
  init: function () {
    if (
      this.Environment.MEDIA_MOUNTED ||
      !this.Environment.isExternalStorageRemovable()
    ) {
      this.AudioPath = this.main.getExternalFilesDir(null).getPath() + '/audios'
      this.AppPath = this.main.getExternalFilesDir(null).getPath()
    } else {
      this.AudioPath = this.main.getFilesDir().getPath() + '/audios'
      this.AppPath = this.main.getFilesDir().getPath()
    }
    console.log('文件存放路径=>', this.AudioPath)
  },

  /**
   * 写入音频到文件
   * @param {...any} args - 要记录的音频内容
   */
  writeData: function (data) {
    const datetime = getTime('YYYYMMDDhhmmss') // 获取完整的时间格式

    // 按日期分割音频文件
    const filePath = this.AudioPath + '/audio_' + datetime + '.mp3'

    // 确保音频目录存在
    let file = new this.File(this.AudioPath)
    if (!file.exists()) {
      file.mkdirs() // 递归创建目录
    }

    // 使用缓冲流写入文件
    let fos = null
    let bw = null
    try {
      fos = new this.FileOutputStream(filePath, true) // true表示追加模式
      bw = new this.BufferedOutputStream(fos)

      const view = new DataView(data)
      for (let i = 0; i < data.byteLength; i++) {
        const byte = view.getUint8(i)
        bw.write(byte)
      }
      bw.flush()
    } catch (e) {
      console.log('写入文件失败=>', e)
    } finally {
      try {
        if (bw != null) bw.close() // 关闭流
        if (fos != null) fos.close()
      } catch (closeEx) {
        console.log('关闭流失败=>', closeEx)
      }
    }
    this.deleteOldLogFiles()
    return filePath
  },
  // 异步存储文件，提高性能
  writeDataAsync: function (data) {
    return new Promise((resolve, reject) => {
      // const fileLib = uni.requireNativePlugin?.('file-tool')
      if (!this.fileLib) {
        reject('本地文件插件加载失败')
      }
      const datetime = getTime('YYYYMMDDhhmmss') // 获取完整的时间格式

      // 按日期分割音频文件
      const filePath = this.AudioPath + '/audio_' + datetime + '.mp3'

      // 确保音频目录存在
      let file = new this.File(this.AudioPath)
      if (!file.exists()) {
        file.mkdirs() // 递归创建目录
      }
      this.fileLib.writeFile(
        filePath,
        this.arrayBufferToHex(data),
        result => {
          if (result['success']) {
            this.deleteOldLogFiles()
            resolve(filePath)
          } else {
            reject('保存文件失败')
          }
        },
        error => {
          reject(error)
        }
      )
    })
  },
  arrayBufferToHex: function (buffer) {
    if (!(buffer instanceof ArrayBuffer)) {
      throw new Error('参数必须是 ArrayBuffer')
    }

    const view = new Uint8Array(buffer)
    let hexString = ''

    for (let i = 0; i < view.length; i++) {
      const hex = view[i].toString(16).padStart(2, '0')
      hexString += hex
    }

    return hexString
  },

  // 删除超过一定数量的旧音频文件
  deleteOldLogFiles: function (maxFileCount = 15) {
    let logFiles = this.getLogFileList()
    // 按照最后修改时间排序
    logFiles.sort(function (a, b) {
      return b.updateTime - a.updateTime
    })
    console.log('总音频文件=>', logFiles)
    if (logFiles.length > maxFileCount) {
      for (let i = maxFileCount; i < logFiles.length; i++) {
        this.removeLogFile(logFiles[i].filePath)
      }
    }
  },

  /**
   * 删除指定音频文件
   * @param {string} filePath - 要删除的文件路径
   */
  removeLogFile: function (filePath) {
    const file = new this.File(filePath)
    const fos = new this.FileOutputStream(filePath, true)
    fos.close()
    file.delete()
    console.log('删除文件=>', filePath)
  },

  /**
   * 删除所有音频文件
   */
  removeAllLogFile: function () {
    const logFiles = this.getLogFileList()
    for (let i = 0; i < logFiles.length; i++) {
      this.removeLogFile(logFiles[i].filePath)
    }
  },

  /**
   * 获取音频文件列表
   * @returns {Array} 返回包含文件名和路径的对象数组
   */
  getLogFileList: function () {
    const list = []
    const file = new this.File(this.AudioPath)
    const tempList = file.listFiles()

    for (let i = 0; i < tempList.length; i++) {
      list.push({
        index: i,
        name: tempList[i].getName(),
        filePath: tempList[i].getPath(),
        size: tempList[i].length(),
        updateTime: tempList[i].lastModified()
      })
    }

    return list
  },

  /**
   * 读取音频文件内容
   * @param {string} filePath - 文件路径
   * @returns {Array} 按行分割的音频内容数组
   */
  readData: function (filePath) {
    let file = new this.File(filePath)
    let buffer = new ArrayBuffer(0)
    try {
      if (!file.exists()) return null

      let fileSize = file.length()
      // 创建 ArrayBuffer
      buffer = new ArrayBuffer(fileSize)
      const dataView = new DataView(buffer)

      let bufferedReader = new this.BufferedInputStream(
        new this.FileInputStream(file)
      )
      for (let idx = 0; idx < fileSize; idx++) {
        let byteData = bufferedReader.read()
        dataView.setUint8(idx, byteData)
      }
      bufferedReader.close()
    } catch (e) {
      console.error('读取文件失败=>', e)
      // 确保资源关闭
      if (bufferedReader) bufferedReader.close()
    }
    return buffer
  },
  readDataAsync: function (filePath) {
    return new Promise((resolve, reject) => {
      if (!this.fileLib) {
        reject('本地文件插件加载失败')
      }

      try {
        let file = new this.File(filePath)
        if (!file.exists()) {
          reject('文件不存在')
        }

        this.fileLib.readFile(
          filePath,
          result => {
            if (result['success']) {
              let hexData = result['fileData']
              let buffer = this.hexToArrayBuffer(hexData)
              resolve(buffer)
            } else {
              reject('读取文件失败')
            }
          },
          error => {
            reject(error)
          }
        )
      } catch (e) {
        reject(e)
      }
    })
  },
  hexToArrayBuffer: function (hexString) {
    // 清理 HEX 字符串（移除空格等）
    const cleanHex = hexString.replace(/[^0-9a-f]/gi, '').toLowerCase()

    // 检查长度是否为偶数
    if (cleanHex.length % 2 !== 0) {
      throw new Error('HEX字符串长度必须为偶数')
    }

    // 创建 ArrayBuffer
    const buffer = new ArrayBuffer(cleanHex.length / 2)
    const view = new Uint8Array(buffer)

    // 逐个字节转换
    for (let i = 0; i < cleanHex.length; i += 2) {
      const byteHex = cleanHex.substr(i, 2)
      const byteValue = parseInt(byteHex, 16)

      if (isNaN(byteValue)) {
        throw new Error(`无效的HEX字符: ${byteHex}`)
      }

      view[i / 2] = byteValue
    }

    return buffer
  },

  // 获取设备剩余存储空间的方法
  getSystemStorage: function () {
    const files = this.Environment.getDataDirectory()
    const statFs = new this.StatFs(files.getPath())
    const blockAva = parseFloat(statFs.getAvailableBlocks())
    const blockSize = parseFloat(statFs.getBlockSize())
    const internalMemSize = blockSize * blockAva

    return {
      rawSize: internalMemSize, // 原始大小
      size: transformByteData(internalMemSize) // 格式化后的值
    }
  }
}

// 初始化音频系统
AudioFileManager.init()
// #endif

// 非APP-PLUS平台的空实现
// #ifndef APP-PLUS
const AudioFileManager = {}
// #endif

/**
 * 时间格式化函数
 * @param {string} [style] - 格式类型(可选)，默认为 'YYYY-MM-DD hh:mm:ss'
 *  可选值:
 *    - 'hh:mm:ss'        : 时:分:秒
 *    - 'YYYY-MM-DD'      : 年-月-日
 *    - 'YYYYMMDD'        : 年月日
 *    - 'YYYY-MM-DD hh:mm:ss' : 年-月-日 时:分:秒 (默认)
 *    - 'YYYYMMDDhhmmss'  : 年月日时分秒
 *    - 'YYYY'            : 年
 *    - 'MM'              : 月
 *    - 'DD'              : 日
 *    - 'getDay'          : 星期几(0-6)
 * @returns {string} 格式化后的时间字符串
 */
const getTime = (style = 'YYYY-MM-DD hh:mm:ss') => {
  const time = new Date()

  // 时间组件补零处理
  const pad = num => (num < 10 ? `0${num}` : num)
  const yyyy = time.getFullYear()
  const mm = pad(time.getMonth() + 1) // 月份从0开始
  const dd = pad(time.getDate())
  const h = pad(time.getHours())
  const m = pad(time.getMinutes())
  const s = pad(time.getSeconds())
  const z = time.getDay() // 星期几(0-6)

  // 格式映射表
  const formats = {
    'hh:mm:ss': `${h}:${m}:${s}`,
    'YYYY-MM-DD': `${yyyy}-${mm}-${dd}`,
    YYYYMMDD: `${yyyy}${mm}${dd}`,
    'YYYY-MM-DD hh:mm:ss': `${yyyy}-${mm}-${dd} ${h}:${m}:${s}`,
    YYYYMMDDhhmmss: `${yyyy}${mm}${dd}${h}${m}${s}`,
    YYYY: yyyy,
    MM: mm,
    DD: dd,
    getDay: z
  }

  return formats[style] || formats['YYYY-MM-DD hh:mm:ss']
}

/**
 * @description 转化字节数据
 * @param {*} data 表示要被转化的容量大小，以字节为单位
 * @param {*} digit 表示如果转换时出小数，四舍五入保留多少位 默认为2位小数
 * @returns
 */
const transformByteData = (data, digit = 2, extension = '') => {
  if (!data) return `0${extension}B`
  const c = 1024
  const e = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
  const i = Math.floor(Math.log(data) / Math.log(c))
  return (data / c ** i).toFixed(digit) + extension + e[i]
}

export default AudioFileManager
